using System;
using System.Collections.Generic;
using System.Text;

namespace H2.Sections
{
    public class LightMap
    {
        #region Instances
        internal int StartOffset;
        private int __sbspInfoIndex;
        private MapStream Map;
        private Palette[] _palettes;
        #endregion

        #region Accessors
        /// <summary>
        /// SbspInfoIndex
        /// </summary>
        public int SbspInfoIndex { get { return __sbspInfoIndex; } }
        /// <summary>
        /// LightMapBitmapID
        /// </summary>
        public int LightMapBitmapID
        {
            get
            {
                long oldPos = Map.Position;
                Map.ReadReflexiveAt(StartOffset + 128, Map.Sbsp[SbspInfoIndex, Tags.SearchType.Index].Magic);
                Map.Position += 28;
                int ID = Map.ReadInt32();
                Map.Position = oldPos;
                return ID;
            }
            set
            {
                long oldPos = Map.Position;
                Map.ReadReflexiveAt(StartOffset + 128, Map.Sbsp[SbspInfoIndex, Tags.SearchType.Index].Magic);
                Map.Position += 28;
                Map.Write(value);
                Map.Position = oldPos;
            }
        }
        /// <summary>
        /// Palettes
        /// </summary>
        public Palette[] Palettes { get { return _palettes; } set { _palettes = value; } }
        /// <summary>
        /// PaletteCount
        /// </summary>
        public int PaletteCount
        { 
            get
            {
                long oldPos = Map.Position;
                Map.ReadReflexiveAt(StartOffset + 128, Map.Sbsp[SbspInfoIndex, Tags.SearchType.Index].Magic);
                Map.Position += 8;
                int count = Map.ReadInt32();
                Map.Position = oldPos;
                return count;
            }
        }
        #endregion

        #region Data
        /// <summary>
        /// Read ID
        /// </summary>
        public int ID { get { return Map.ReadInt32At(Map.Sbsp.SbspInfoCache[SbspInfoIndex].StartOffset + 28, false); } set { Map.WriteAt(Map.Sbsp.SbspInfoCache[SbspInfoIndex].StartOffset + 28, value, false); } }
        /// <summary>
        /// Read TagPath
        /// </summary>
        public string TagPath { get { return Map.Tags.GetTagPath(ID, Tags.SearchType.ID); } }
        /// <summary>
        /// Read Offset
        /// </summary>
        public int Offset { get { return Map.ReadInt32At(Map.Sbsp.SbspInfoCache[SbspInfoIndex].Offset + 8, false) - Map.Sbsp.SbspInfoCache[SbspInfoIndex].Magic; } set { Map.WriteAt(Map.Sbsp.SbspInfoCache[SbspInfoIndex].StartOffset + 8, value + Map.Sbsp.SbspInfoCache[SbspInfoIndex].Magic, false); } }
        /// <summary>
        /// Calculate Size
        /// </summary>
        public int Size { get { return (Map.Sbsp.SbspInfoCache[SbspInfoIndex].Offset + Map.Sbsp.SbspInfoCache[SbspInfoIndex].Size) - Offset; } }
        ///// <summary>
        ///// PalettesOffset
        ///// </summary>
        //public int PalettesOffset { get { return __palettesOffset__; } set { __palettesOffset__ = value; } }
        ///// <summary>
        ///// Palettes
        ///// </summary>
        //public List<PaletteColor[]> Palettes { get { return __palettes__; } set { WritePalettes(value); } }
        ///// <summary>
        ///// Bsp_Submap_Indices
        ///// </summary>
        //public int[] Bsp_Submap_Indices { get { return __bsp_Submap_Indices__; } set { __bsp_Submap_Indices__ = value; } }
        ///// <summary>
        ///// Bsp_Palette_Indices
        ///// </summary>
        //public int[] Bsp_Palette_Indices { get { return __bsp_Palette_Indices__; } set { __bsp_Palette_Indices__ = value; } }
        ///// <summary>
        ///// Perm_Submap_Indices
        ///// </summary>
        //public int[] Perm_Submap_Indices { get { return __perm_Submap_Indices__; } set { __perm_Submap_Indices__ = value; } }
        ///// <summary>
        ///// Perm_Palette_Indices
        ///// </summary>
        //public int[] Perm_Palette_Indices { get { return __perm_Palette_Indices__; } set { __perm_Palette_Indices__ = value; } }

        #endregion

        internal LightMap(MapStream map, int sbspInfoIndex)
        {
            Map = map;
            __sbspInfoIndex = sbspInfoIndex;
        }

        internal void CreatePaletteCache()
        {
            Map.ReadReflexiveAt(StartOffset + 128, Map.Sbsp[SbspInfoIndex, Tags.SearchType.Index].Magic);
            Map.Position += 8;
            int count = Map.ReadInt32();

            Palettes = new Palette[count];
            for (int i = 0; i < count; i++)
                Palettes[i] = new Palette(Map, (int)Map.Position + (i * 1024));
        }

        public class Palette
        {
            MapStream Map;

            private int _offset;
            public int Offset { get { return _offset; } set { _offset = value; } }

            private Bitmaps.RGBA_ByteColor[] ColorsCache;
            public Bitmaps.RGBA_ByteColor[] Colors { get { return ColorsCache; } set { ColorsCache = value; } }

            internal Palette(MapStream map, int offset)
            {
                Map = map;
                Offset = offset;
                CreateCache();
            }

            internal void CreateCache()
            {
                ColorsCache = new Bitmaps.RGBA_ByteColor[256];
                for (int i = 0; i < 256; i++)
                {
                    ColorsCache[i].R = Map.ReadByte();
                    ColorsCache[i].G = Map.ReadByte();
                    ColorsCache[i].B = Map.ReadByte();
                    ColorsCache[i].A = Map.ReadByte();
                }
            }

            public void Flush()
            {
                long oldPos = Map.Position;
                Map.Position = Offset;
                for (int i = 0; i < 256; i++)
                {
                    Map.Write(ColorsCache[i].R);
                    Map.Write(ColorsCache[i].G);
                    Map.Write(ColorsCache[i].B);
                    Map.Write(ColorsCache[i].A);
                }
                Map.Position = oldPos;
                Map.Flush();
            }
        }
    }
}
